--- %%NOBANNER%% -->
![]() | ![]() |
/*------------------<--- Start of Description -->--------------------\ | survlrk.SAS -- calculates logrank statistics for the surv macro. | | It created no printout, but returns an output dataset to the | | calling program. | | Note: PROC IML will be needed for the Macro; | |--------------------<--- End of Description -->---------------------| |--------------------------------------------------------------------| |--------------<--- Start of Files or Arguments Needed -->-----------| | The following argumentss must be defined: | | data= the data set to be analyzed; | | time= the name of the TIME variable; | | death= the name of the DEATH variable; | | censor= the censor value, usually 0. | | strata= the name of the STRATA or class variable; | | out= the name of the output dataset. This dataset will | | contain one observation with: | | &strata = the strata or class variable; | | observed = the calculated number of observed; | | expected = the calculated number of expected; | | o_e = number observed - expected; | | rr = the relative risk (observed/expected for this strata | | / observed/expected for strata 1); | | chisq = the chi-square value. | | df = degrees of freedom | | pvalue = the p-value for the probability of a greater chisq. | |--------------<--- Start of Files or Arguments Needed -->-----------| |--------------------------------------------------------------------| |----------------<--- Start of Example and Usage -->-----------------| | Usage: %survlrk(data= ,time= ,death= ,censor= ,strata= ,out= ); | \-------------------<--- End of Example and Usage -->---------------*/ %macro survlrk(data= ,time= ,death= ,censor= ,strata= ,out= ); /*--------------------------------------------\ | Author: David J. Camp, Michael A. Province| | E. Bergstralh and Jan Offord; | | Created: 1993; | | Modified: 6/2/1993; | | Purpose: Calculates logrank statistics; | \--------------------------------------------*/ run; %let tol=1e-10; /* check for only one strata */ data _lrmstr; set &data; if &time=. or &event=. then delete; proc freq data=_lrmstr; tables &strata/ out=_lr1 noprint; data &out; set _lr1 end=eof; keep &strata observed expected o_e rr chisq df pvalue; observed=.; expected=.; o_e=.; rr=.; chisq=.; df=.; pvalue=.; if eof=1 then do; call symput('num_st',left(put(_n_,2.))); end; run; %if &num_st<=1 %then %do; %put "WARNING - only one strata - log-rank test cannot be done"; %end; /* main processing */ %if &num_st>1 %then %do; proc sort data=_lrmstr; by &time; /* Invoke IML for the rest of the processing. */ proc iml worksize=128; reset log; use _lrmstr; top = 0; obs = 0; /* determine number and names of the strata */ do data; read next; obs = obs + 1; this = 0; do i = 1 to top; if &strata = strats [i] then this = i; end; if this = 0 then do; pop = pop // {0}; strats = strats // &strata; top = top + 1; this = top; end; pop [this] = pop [this] + 1; end; close _lrmstr; /* Reopen dataset for calculation phase */ use _lrmstr; d = j (top, 1, 0); /* 'd' is deaths this time, each strata. */ c = j (top, 1, 0); /* 'c' is cases this time, each strata. */ v = j (top, 1, 0); /* 'v' is vector for Log Rank. */ e_lr = j (top, 1, 0); /* 'e_lr' is vector of expecteds --ejb */ o_lr = j (top, 1, 0); /* 'o_lr' is vector of obs --ejb */ w = j (top, 1, 0); /* 'w' is vector for Wilcoxon. */ sv = j (top, top, 0); /* 'sv' is array for Log Rank. */ sw = j (top, top, 0); /* 'sw' is array for Wilcoxon. */ n = pop; /* 'n' is population left, each strata. */ t = .; /* 't' is current time. */ obs = 0; /* 'obs' is observation counter. */ do data; read next; obs = obs + 1; do i = 1 to top; if &strata = strats [i] then this = i; end; if t ^= . & t ^= &time then do; dc = sum (d); nc = sum (n); do i = 1 to top; temp = d [i] - n [i] * dc / nc; expd =n[i]*dc/nc; **log rank expected events..ejb; if n[i]=nc then expd=0; **only one group left..ejb; obs = d[i]; **log rank observed events...ejb; if n[i]=nc then obs =0; o_lr [i] = o_lr [i]+ obs; ** events for logrank test..ejb; e_lr [i] = e_lr[i] + expd; v [i] = v [i] + temp; w [i] = w [i] + nc * temp; end; do l = 1 to top; do j = l to top; delta = (j = l); temp = (nc * n[l] * delta - n [j] * n [l]) * (dc * (nc - dc) / (nc * nc * (nc - 1))); sv [l, j] = sv [l, j] + temp; sw [l, j] = sw [l, j] + nc * nc * temp; end; end; n = n - c; c = j (top, 1, 0); d = j (top, 1, 0); end; t = &time; c [this] = c [this] + 1; if &death ^= &censor then d [this] = d [this] + 1; end; /* Fill in the bottom of the symmmetric arrays. */ do l = 2 to top; do j = 1 to l - 1; sv [l, j] = sv [j, l]; sw [l, j] = sw [j, l]; end; end; /* Calculate the statistics. */ o_e = j (top, 3, 0); /* 'initialize to zero --jro */ stats = j (2, 3, 0); /* 'initialize to zero --jro */ qv = v` * ginv (sv) * v; qw = w` * ginv (sw) * w; ev = eigval (sv); ew = eigval (sw); dv = 0; dw = 0; do i = 1 to top; if ev [i] > &tol then dv = dv + 1; if ew [i] > &tol then dw = dw + 1; end; pv = 1 - probchi (qv, dv); pw = 1 - probchi (qw, dw); o_e=o_lr || e_lr || (o_lr-e_lr); *observed, expected, o-e, ejb; logrank = sv || v; wilcoxon = sw || w; varnames={"observed" "expected" "o_e"}; /* create the output datasets */ create _lr1 from o_e [ rowname=strats colname=varnames]; append from o_e [rowname=strats]; names = {"Log Rank" "Wilcoxon"}; stats = (qv // qw) || (dv // dw) || (pv // pw); varnames={"chisq" "df" "pvalue"}; create _lr2 from stats [ rowname=names colname=varnames]; append from stats [rowname=names]; if (dv ^= top - 1) | (dw ^= top - 1) then print "Warning -- The degrees of freedom ^= strats-1."; quit; /* merge the output datasets */ data &out; set _lr1; keep &strata observed expected o_e chisq df pvalue; &strata=strats; if _n_=1 then do; set _lr2; end; proc sort; by &strata; data &out; set &out; drop rr1; retain rr1; if _n_=1 then do; if expected>0 then rr1=observed/expected; else rr1=.; end; if expected>0 and rr1>0 then rr=(observed/expected)/rr1; else rr=.; if _n_^=1 then do; df=.; chisq=.; pvalue=.; end; %end; run; %mend survlrk;